home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 2: Applications
/
Linux Cubed Series 2 - Applications.iso
/
circuits
/
irsim-9.000
/
irsim-9
/
src
/
irsim
/
genspktbl.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-15
|
10KB
|
355 lines
/*
* *********************************************************************
* * Copyright (C) 1988, 1990 Stanford University. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. Stanford University *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*/
/*
* Program to generate the spike fluctuation and delay lookup tables.
*/
#include <stdio.h>
#include <math.h>
extern void exit();
/* forward references */
void BuildTables(), PrintTable(), linear_spike(), rk4_error();
void nldh_vector(), nldl_vector();
double nldh_rk4(), nldl_rk4();
#define SPIKETBLSIZE 10
#define STEP (1.0 / SPIKETBLSIZE) /* Step of computation */
#define NLSPKMIN 0
#define NLSPKMAX 1
#define LINEARSPK 2
double nldltab[ SPIKETBLSIZE + 1 ][ SPIKETBLSIZE + 1 ];
double nldhtab[ SPIKETBLSIZE + 1 ][ SPIKETBLSIZE + 1 ];
double linrtab[ SPIKETBLSIZE + 1 ][ SPIKETBLSIZE + 1 ];
double delaytab[ SPIKETBLSIZE + 1 ][ SPIKETBLSIZE + 1 ];
#define SMALL 0.01
#define LARGE 0.99
FILE *F;
main( argc, argv )
int argc;
char *argv[];
{
char *fname;
char *size = "SPIKETBLSIZE";
if( argc == 1 )
fname = "spiketbl.c";
else if( argc == 2 )
fname = argv[1];
else
fprintf( stderr, "Usage: genspktbl [filename]\n" ), exit( 1 );
if( (F = fopen( fname, "w" )) == NULL )
fprintf( stderr, "can not open `%s'\n", fname ), exit( 1 );
BuildTables();
fprintf( F, "/* DO NOT EDIT. THIS FILE IS GENERATED BY genspktbl */\n\n" );
fprintf( F, "#define SPIKETBLSIZE %d\n\n", SPIKETBLSIZE );
fprintf( F, "#define NLSPKMIN %d\n", NLSPKMIN );
fprintf( F, "#define NLSPKMAX %d\n", NLSPKMAX );
fprintf( F, "#define LINEARSPK %d\n", LINEARSPK );
fprintf( F, "\n" );
fprintf( F, "static float spikeTable[ 3 ][ %s + 1 ][ %s + 1 ] =\n{\n",
size, size );
fprintf( F, "\t/* non-linear nmos driven low / pmos driven high */\n" );
PrintTable( nldltab, "%.3f" );
fprintf( F, "\n\t/* non-linear nmos driven high / pmos driven low */\n" );
PrintTable( nldhtab, "%.3f" );
fprintf( F, "\n\t/* linear RC (nmos-pmos mix)*/\n" );
PrintTable( linrtab, "%.3f" );
fprintf( F, "};\n\n" );
fprintf( F, "static float delayTable[ %s + 1 ][ %s + 1 ] = \n{\n",
size, size );
PrintTable( delaytab, "%.5e" );
fprintf( F, "};\n" );
exit( 0 );
/* NOTREACHED */
}
void PrintTable( tab, fmt )
double tab[ SPIKETBLSIZE+1 ][ SPIKETBLSIZE+1 ];
char *fmt;
{
register int alpha, beta;
for( beta = 0; beta <= SPIKETBLSIZE; beta++ )
{
if( beta == 0 )
fprintf( F, "/* .01 */" );
else if( beta == SPIKETBLSIZE )
fprintf( F, "/* .99 */" );
else
fprintf( F, "/* 0.%d */", beta );
for( alpha = 0; alpha <= SPIKETBLSIZE; alpha++ )
{
fprintf( F, " " );
fprintf( F, fmt, tab[ beta ][ alpha ] );
fprintf( F, "," );
if( (alpha + 1) % 4 == 0 )
fprintf( F, "\n " );
}
fprintf( F, "\n" );
}
}
/*
* Peak voltage for a 2-transistors-2-capacitors network, as a function
* of alpha and beta. Compute spikes for nmos network driven to Gnd and
* to Vdd, placing the results in nldltab and nldhtab respectively.
*
* Alpha is the ratio of resistance of the resistor closer to the driver to
* the total resistance.
* Beta is the ratio of capacitance of the capacitor closer to the driver to
* the total capacitance.
*
*/
void BuildTables()
{
double alpha, beta, step;
register int i, j;
for( beta = SMALL, i = 0; i <= SPIKETBLSIZE; i++ )
{
if( i == SPIKETBLSIZE )
beta = LARGE;
for( alpha = SMALL, j = 0; j <= SPIKETBLSIZE; j++ )
{
if( j == SPIKETBLSIZE )
alpha = LARGE;
if( (alpha < .0399) || (alpha > .9601) )
step = .0001;
else if( (alpha < .0999) || (alpha > .9001) )
step = .001;
else
step = .01;
if( (beta < .0399) || (beta > .9601) )
step = .0001;
else if( (beta < .0999) || (beta > .9001) )
step = (step < .0009) ? step : .001;
nldltab[ i ][ j ] = nldl_rk4( alpha, beta, step );
nldhtab[ i ][ j ] = 1.0 - nldh_rk4( alpha, beta, step );
linear_spike( alpha, beta, &(delaytab[i][j]), &(linrtab[i][j]) );
if( alpha == SMALL )
alpha = STEP;
else
alpha += STEP;
}
if( beta == SMALL )
beta = STEP;
else
beta += STEP;
}
}
void rk4_error( which, alpha, beta, h )
char *which;
double alpha, beta, h;
{
fprintf( stderr, "RK4 error: %s: Didn't reach the peak\n", which );
fprintf( stderr, "alpha = %f beta = %f h = %f\n", alpha, beta, h );
exit( 1 );
}
/*
* 4th order Runge-Kutta method to solve 2-transistors-2-capacitors
* networks assuming quadratic transistor model.
*
* 1) Driven path is ground.
* 2) Node 1 is discharged initially, and the ratio of its capacitance
* to the total capacitance is equal to beta.
* 3) The ratio of resistance of the resistor closer to ground to the
* total resistrance is equal to alpha.
* 4) Step size is h.
* 5) Return the peak voltage observed at node 1.
*
* This routine is numerically stable when
* i) h == .001; .04 < alpha < .96; .04 < beta < .96
* ii) h == .01; .1 < alpha < .9; .1 < beta < .9
*/
double nldl_rk4( alpha, beta, h )
double alpha, beta, h;
{
double k11, k12, k21, k22, k31, k32, k41, k42;
double v1old, v1new, v2old, v2new;
double tmp1, tmp2;
register int i, j;
v1old = 0.0; /* Initial Voltages */
v2old = 1.0;
j = (int) (1.0 / h); /* Maximum number of iterations */
for( i = 0; i < j; i++ )
{
nldl_vector( alpha, beta, h, v1old, v2old, &k11, &k12 );
tmp1 = v1old + .5 * k11;
tmp2 = v2old + .5 * k12;
nldl_vector( alpha, beta, h, tmp1, tmp2, &k21, &k22 );
tmp1 = v1old + .5 * k21;
tmp2 = v2old + .5 * k22;
nldl_vector( alpha, beta, h, tmp1, tmp2, &k31, &k32 );
tmp1 = v1old + k31;
tmp2 = v2old + k32;
nldl_vector( alpha, beta, h, tmp1, tmp2, &k41, &k42 );
v1new = v1old + (k11 + 2.0 * k21 + 2.0 * k31 + k41) / 6.0;
v2new = v2old + (k12 + 2.0 * k22 + 2.0 * k32 + k42) / 6.0;
if (v1new < v1old)
return( v1old ); /* v1old is the peak */
v1old = v1new;
v2old = v2new;
}
/* i >= j */
rk4_error( "nldl", alpha, beta, h );
return( 0.0 );
}
/*
* This routine computes the parameter vector for Runge-Kutta method.
* Customized for 2-transistors-2-capacitors network driven by Gnd.
*/
void nldl_vector( alpha, beta, h, v1, v2, k1, k2 )
double alpha, beta, h, v1, v2, *k1, *k2;
{
double u1, u2;
u1 = 2.0 * v1 - v1 * v1;
u2 = 2.0 * v2 - v2 * v2;
*k1 = h * (alpha * u2 - u1) / ( alpha * beta * (1.0 - alpha) );
*k2 = h * (u1 - u2) / ((1.0 - alpha) * (1.0 - beta));
}
/*
* 4th order Runge-Kutta method to solve 2-transistors-2-capacitors
* networks assuming quadratic transistor model.
*
* 1) Driven path is Vdd.
* 2) Node 1 is charged high initially, and the ratio of its capacitance
* to the total capacitance is equal to beta.
* 3) The ratio of resistance of the resistor closer to driver to the
* total resistrance is equal to alpha.
* 4) Step size is h.
* 5) Return the peak voltage observed at node 1.
*
* This routine is numerically stable when
* i) h == .001; .04 < alpha < .96; .04 < beta < .96
* ii) h == .01; .1 < alpha < .9; .1 < beta < .9
*/
double nldh_rk4( alpha, beta, h )
double alpha, beta, h;
{
double k11, k12, k21, k22, k31, k32, k41, k42;
double v1old, v1new, v2old, v2new;
double tmp1, tmp2;
register int i, j;
v1old = 1.0; /* Initial Voltages */
v2old = 0.0;
j = (int) (1.0 / h); /* Maximum number of iterations */
for( i = 0; i < j; i ++ )
{
nldh_vector( alpha, beta, h, v1old, v2old, &k11, &k12 );
tmp1 = v1old + .5 * k11;
tmp2 = v2old + .5 * k12;
nldh_vector( alpha, beta, h, tmp1, tmp2, &k21, &k22 );
tmp1 = v1old + .5 * k21;
tmp2 = v2old + .5 * k22;
nldh_vector( alpha, beta, h, tmp1, tmp2, &k31, &k32 );
tmp1 = v1old + k31;
tmp2 = v2old + k32;
nldh_vector( alpha, beta, h, tmp1, tmp2, &k41, &k42 );
v1new = v1old + (k11 + 2.0 * k21 + 2.0 * k31 + k41) / 6.0;
v2new = v2old + (k12 + 2.0 * k22 + 2.0 * k32 + k42) / 6.0;
if( v1new > v1old )
return( v1old ); /* v1old is the peak */
v1old = v1new;
v2old = v2new;
}
/* i >= j */
rk4_error( "nldh", alpha, beta, h );
return( 0.0 );
}
/*
* This routine computes the parameter vector for Runge-Kutta method.
* Customized for 2-transistors-2-capacitors network driven by Vdd.
*/
void nldh_vector( alpha, beta, h, v1, v2, k1, k2 )
double alpha, beta, h, v1, v2, *k1, *k2;
{
double u1, u2;
u1 = 1.0 - 2.0 * v1 + v1 * v1;
u2 = 1.0 - 2.0 * v2 + v2 * v2;
*k1 = -h * (alpha * u2 - u1) / ( alpha * beta * (1.0 - alpha) );
*k2 = -h * (u1 - u2) / ((1.0 - alpha) * (1.0 - beta));
}
/*
* Compute spike fluctuation and delay using an rc linear model.
* Use equations for driven by Gnd case
*/
void linear_spike( alpha, beta, delay, peak )
double alpha, beta, *delay, *peak;
{
double N, b, a, x, tmp;
tmp = alpha * beta + 1.0 - beta;
N = alpha * beta * (1.0 - alpha) * (1.0 - beta) / (tmp * tmp);
a = sqrt( 1.0 - 4.0 * N );
x = (1.0 - a) / (1.0 + a);
b = (1.0 + x) * exp( x * log( x ) / (1.0 - x) );
*peak = b * alpha * (1.0 - beta) / tmp;
x = (1.0 + a) / (1.0 - a);
b = log( x ) / a;
*delay = b * beta * (1.0 - alpha) / alpha;
}